import { Inject } from '@nestjs/common';
import { paramsKeyFormat } from '../../utils/decorator';
import { RedisService } from '../redis/redis.service';

export function Cacheable(
  CACHE_NAME: string,
  CACHE_KEY: string,
  CACHE_EXPIRESIN?: number,
) {
  // 返回一个装饰器函数
  const injectRedis = Inject(RedisService);

  return function (
    target: any,
    propertyKey: string,
    descriptor: PropertyDescriptor,
  ) {
    injectRedis(target, 'redis');

    // 保存原有方法，以便在缓存未命中时调用 getConfigValue
    const originMethod = descriptor.value;

    // 重写方法，在方法执行前先从缓存中获取数据，如果缓存命中则直接返回缓存数据，否则执行原方法并缓存结果
    descriptor.value = async function (...args: any[]) {
      // 生成缓存键
      const key = paramsKeyFormat(originMethod, CACHE_KEY, args);
      // 如果 key 为 null，则直接调用原始方法。
      if (key === null) {
        return await originMethod.apply(this, args);
      }
      const cacheResult = await this.redis.get(`${CACHE_NAME}${key}`);

      if (!cacheResult) {
        const result = await originMethod.apply(this, args);

        await this.redis.set(`${CACHE_NAME}${key}`, result, CACHE_EXPIRESIN);

        return result;
      }

      return cacheResult;
    };
  };
}
